package com.jianjun.ktui

import androidx.compose.material3.CalendarLocale
import androidx.compose.material3.ExperimentalMaterial3Api
import cn.hutool.core.lang.Dict
import cn.hutool.core.thread.ThreadUtil
import cn.hutool.http.HttpRequest
import cn.hutool.http.HttpResponse
import cn.hutool.http.HttpStatus
import com.fasterxml.jackson.core.json.JsonReadFeature
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.jianjun.ktui.ui.data.BaseException
import com.jianjun.ktui.ui.data.UserStore
import com.jianjun.ktui.util.UtilSsl
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

var objectMapper: ObjectMapper = ObjectMapper()
    //允许未转义控制字符\n等
    .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
    //属性字段允许为对象json字符串
    .enable(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature())
    // 没有 getter 方法时不抛异常
    .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
    //在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
    .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
    // 自动发现并注册所有可用的 jackson 模块
    .findAndRegisterModules()

class JVMPlatform : Platform {
    override val name: String = "Java ${System.getProperty("java.version")}"
}

actual fun getPlatform(): Platform = JVMPlatform()

actual suspend fun <T> httpRuoYi(
    path: String,
    params: MutableMap<String, Any>,
    method: Method
): T {
    val future = ThreadUtil.execAsync<T> {
        val httpRequest: HttpRequest = when (method) {
            Method.GET -> HttpRequest.get(getPlatform().urlRuoYi + path)
            Method.POST -> HttpRequest.post(getPlatform().urlRuoYi + path)
            Method.PUT -> HttpRequest.put(getPlatform().urlRuoYi + path)
            Method.DELETE -> HttpRequest.delete(getPlatform().urlRuoYi + path)
        }
        httpRequest.setSSLSocketFactory(UtilSsl.sslSocketFactory)
        if (UserStore.token.isNotEmpty()) {
            httpRequest.header("Authorization", "Bearer " + UserStore.token)
        }
        when (method) {
            Method.GET, Method.DELETE -> httpRequest.form(params)
                .header("Content-Type", "application/x-www-form-urlencoded")

            Method.POST, Method.PUT -> httpRequest.header("Content-Type", "application/json")
                .body(objectMapper.writeValueAsString(params))

        }
        val httpResponse: HttpResponse = httpRequest.execute()
        if (HttpStatus.HTTP_OK == httpResponse.status) {
            val body: Dict = objectMapper.readValue(httpResponse.body(), Dict::class.java)
            if (HttpStatus.HTTP_OK == body.getInt("code")) {
                return@execAsync objectMapper.readValue(httpResponse.body(), object : TypeReference<T>() {
                })
            } else {
                throw BaseException(body.getStr("msg"))
            }
        } else {
            throw BaseException(httpResponse.body())
        }
    }
    return withContext(Dispatchers.IO) {
        future.get()
    }
}

@OptIn(markerClass = [ExperimentalMaterial3Api::class])
actual fun defaultLocale(): CalendarLocale {
    return java.util.Locale.getDefault()
}